package com.glink.common.util;

import com.glink.common.contants.BaseConstants;
import com.glink.common.exception.GeneralSimpleException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.*;

/**
 * 全局常用工具定义在此
 * @author qiushaoshan
 */
@Slf4j
public class BaseCommonUtils {
    /**
     * 精确到秒的普通日期时间  yyyy-MM-dd HH:mm:ss
     */
    public final static FastDateFormat DATE_FORMAT_SECOND_0 = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_DATETIME);

    /**
     * 精确到毫秒的日期时间  yyyy-MM-dd HH:mm:ss.SSS
     */
    public final static FastDateFormat DATE_FORMAT_MILLISECOND_1 = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_DATETIME_MILLISECOND);

    /**
     * 精确到月日期格式 yyyy-MM
     */
    public final static FastDateFormat DATE_FORMAT_MONTH = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_SHORT_DATE_4);
    

    /**
     * 精确到天日期格式1  yyyyMMdd
     */
    public final static FastDateFormat DATE_FORMAT_DAY_2 = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_SHORT_DATE_2);
    /**
     * 精确到天日期格式2 yyyy-MM-dd
     */
    public final static FastDateFormat DATE_FORMAT_DAY_3 = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_SHORT_DATE_3);

    /**
     * 精确到时分期格式 yyyy-MM-dd HH:mm
     */
    public final static FastDateFormat DATE_FORMAT_DAY_5 = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_DATETIME_MINUTE);

    /**
     * 只有小时分钟秒 HH:mm:ss
     */
    public final static FastDateFormat DATE_FORMAT_HOUR_MI_SECOND = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_DATETIME_HOUR_MI_SECOND);

    /**
     * 只有小时分钟 HH:mm
     */
    public final static FastDateFormat DATE_FORMAT_HOUR_MI = FastDateFormat.getInstance(BaseConstants.DATE_FORMAT_DATETIME_HOUR_MI);

    public final static SnowFlakeUtils SNOW_FLAKE_UTILS = new SnowFlakeUtils(7, 17);
    
    public static String generateUUID() {
        String uuid = UUID.randomUUID().toString();
        return uuid.replace("-", "");
    }


    public static Date getCurrentDate() {
        return new Date();
    }

    /**
     * 返回 custom header value
     *
     * @return
     */
    public static String[] findCustomHeaderValue(String... headers) {
        String[] ret = new String[headers.length];
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(servletRequestAttributes)) {
            return new String[0];
        }
        int i = 0;
        for (String header : headers) {
            ret[i++] = servletRequestAttributes.getRequest().getHeader(header);
        }
        return ret;
    }

    /**
     * 获取当前登录用户的orgID
     *
     * @return
     * @throws GeneralSimpleException
     */
    public static String extractOrdIdByToken() throws GeneralSimpleException {
        String[] headers = BaseCommonUtils.findCustomHeaderValue("orgId");
        if (headers.length <= 0) {
            return null;
        } else {
            return headers[0];
        }
    }
    
    /**
     * 获取当前登录用户的personID
     *
     * @return
     * @throws GeneralSimpleException
     */
    public static String extractUserIdtByToken() throws GeneralSimpleException {
        String[] headers = BaseCommonUtils.findCustomHeaderValue("userId");
        if (headers.length <= 0) {
            return null;
        } else {
            return headers[0];
        }
    }

    /**
     * 通过token获取用户名称
     * @return 用户名称
     * @throws GeneralSimpleException 异常信息
     */
    public static String extractUserNameByToken() throws GeneralSimpleException {
        String[] headers = BaseCommonUtils.findCustomHeaderValue("userName");
        if (headers.length <= 0) {
            return null;
        } else {
            return headers[0];
        }
    }

    /**
     * 返回 Header
     *
     * @return
     */
    public static HttpServletRequest findHeaderRequest() {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(servletRequestAttributes)) {
            return null;
        } else {
            return servletRequestAttributes.getRequest();
        }
    }

    public static String findAuthorizationHeader() {
        HttpServletRequest request = findHeaderRequest();
        if (Objects.nonNull(request)) {
            String authorization = request.getHeader(BaseConstants._AUTHORIZATION);
            log.info(BaseConstants._AUTHORIZATION + " : {}", authorization);
            return authorization;
        }
        return null;
    }


    public static String getNowDateTime() {
        return DATE_FORMAT_SECOND_0.format(LocalDateTime.now());
    }

    public static Date parseDate(String input) {
        try {
            return DATE_FORMAT_SECOND_0.parse(input);
        } catch (Throwable e) {
            log.warn(e.getLocalizedMessage(), e);
        }
        return null;
    }

    public static String nextIdAsString() {
        return String.valueOf(SNOW_FLAKE_UTILS.nextId());
    }

    /**
     * @MethodName: getNullPropertyNames
     * @Params: [source]
     * @Return: java.lang.String[]
     * @Author: Yjfqb
     * @Description: 返回指定类所有值为空的属性名称，配合BeanUtils.copyProperties使用会忽略值为Null的拷贝
     * @Date: 2020/9/23 16:24
     **/
    public static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) {
                emptyNames.add(pd.getName());
            }
        }
        return emptyNames.toArray(new String[0]);
    }

    /***
     * 获取客户端ip地址
     * @param request
     */
    public static String getIP(final HttpServletRequest request) throws Exception {
        if (request == null) {
            throw (new Exception("HttpServletRequest is null"));
        }
        String ipStr = request.getHeader("x-forwarded-for");
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getHeader("Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getHeader("WL-Proxy-Client-IP");
        }
        if (StringUtils.isBlank(ipStr) || "unknown".equalsIgnoreCase(ipStr)) {
            ipStr = request.getRemoteAddr();
        }

        // 多个路由时，取第一个非unknown的ip
        final String[] arr = ipStr.split(",");
        for (final String str : arr) {
            if (!"unknown".equalsIgnoreCase(str)) {
                ipStr = str;
                break;
            }
        }
        //目的是将localhost访问对应的ip 0:0:0:0:0:0:0:1 转成 127.0.0.1。
        return "0:0:0:0:0:0:0:1".equals(ipStr) ? "127.0.0.1" : ipStr;
    }
}